package config

import (
	"errors"
	"gitee.com/baal1990/gitee.com/baal1990/cmd/server/app/global"
	"gitee.com/baal1990/gitee.com/baal1990/pkg/crypto"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
	"io/ioutil"
	"path/filepath"
	"strings"
)

var (
	gConfig      GlobalConfig
	symmetricKey = []byte("310c4dbc712ce3bc") // 对称加密key
)

// GlobalConfig 配置信息
type GlobalConfig struct {
	Server          ServerConfig           `mapstructure:"server"`
	Database        DatabaseConfig         `mapstructure:"database"`
	Log             LogConfig              `mapstructure:"log"`
	Redis           RedisConfig            `mapstructure:"redis"`
	Email           EMailConfig            `mapstructure:"email"`
	Sms             SmsConfig              `mapstructure:"sms"`
	MsgcodeGenerato MsgcodeGeneratorConfig `mapstructure:"msgcode-generator"`
	SnowFlake       SnowFlakeConfig        `mapstructure:"snowflake"`
	UriControl      UriControlConfig       `mapstructure:"uri-control"`
	Crypto          CryptoConfig           `mapstructure:"crypto"`
	Token           TokenConfig            `mapstructure:"token"`
}

// ServerConfig 配置信息
type ServerConfig struct {
	Port           string   `mapstructure:"port"`
	TrustedProxies []string `mapstructure:"trusted-proxies"`
}

// DatabaseConfig 配置信息
type DatabaseConfig struct {
	Source string `mapstructure:"source"`
	Driver string `mapstructure:"driver"`
	Open   int    `mapstructure:"open"`
	Idle   int    `mapstructure:"idle"`
}

// LogConfig 配置信息
type LogConfig struct {
	Level         string `mapstructure:"level"`
	Format        string `mapstructure:"format"`
	Prefix        string `mapstructure:"prefix"`
	Director      string `mapstructure:"director"`
	LinkName      string `mapstructure:"link-name"`
	ShowLine      bool   `mapstructure:"show-line"`
	EncodeLevel   string `mapstructure:"encode-level"`
	StacktraceKey string `mapstructure:"stacktrace-key"`
	LogInConsole  bool   `mapstructure:"log-in-console"`
}

// RedisConfig 配置信息
type RedisConfig struct {
	Address    string `mapstructure:"address"`
	Password   string `mapstructure:"password"`
	Open       int    `mapstructure:"open"`
	IdleTimout int    `mapstructure:"idle-timeout"`
}

// EMailConfig 邮箱配置信息
type EMailConfig struct {
	Mailhost string `yaml:"mailhost"` //邮箱发送服务器（SMTP）
	Mailport int    `yaml:"mailport"` //邮箱端口
	Mailuser string `yaml:"mailuser"` //邮箱用户名
	Mailpwd  string `yaml:"mailpwd"`  //邮箱密码或授权码
}

// SmsConfig 短信配置
type SmsConfig struct {
	AppKey    string          `mapstructure:"app-key"`
	AppSecret string          `mapstructure:"app-secret"`
	Host      string          `mapstructure:"host"`
	Code      SmsTemplateInfo `mapstructure:"code"`
	Notify    SmsTemplateInfo `mapstructure:"notify"`
}

// SmsTemplateInfo 短信模板信息
type SmsTemplateInfo struct {
	Sign     string `mapstructure:"sign"`
	Template string `mapstructure:"template"`
}

// MsgcodeGeneratorConfig 短信验证码生成器
type MsgcodeGeneratorConfig struct {
	MsgcodeFreezeTime     int `mapstructure:"msgcode-freeze-time"`
	MsgcodeDurationCount  int `mapstructure:"msgcode-duration-count"`
	MsgcodeDurationWindow int `mapstructure:"msgcode-duration-window"`
	MsgcodeValidTime      int `mapstructure:"msgcode-valid-time"`
	MsgcodeWrongTime      int `mapstructure:"msgcode-wrong-time"`
}

// SnowFlakeConfig 配置信息
type SnowFlakeConfig struct {
	Node int64 `mapstructure:"node"`
}

// UriControlConfig 配置信息
type UriControlConfig struct {
	Expire int `mapstructure:"expire"`
	Max    int `mapstructure:"max"`
}

// CryptoConfig 配置信息
type CryptoConfig struct {
	AsymmetricPrivateKey string `mapstructure:"asymmetric-private-key"`
	SymmetricKey         string `mapstructure:"symmetric-key"`
}

// TokenConfig 配置信息
type TokenConfig struct {
	Key    string `mapstructure:"key"`
	Expire int    `mapstructure:"expire"`
}

// Load 加载配置
func Load(file string) error {
	// 导入配置文件
	fileName := strings.Split(filepath.Base(file), ".")
	if len(fileName) != 2 {
		return errors.New("invalid config file[" + file + "]")
	}
	dir := filepath.Dir(file)
	viper.SetConfigName(fileName[0])
	viper.SetConfigType(fileName[1])
	viper.AddConfigPath(dir)
	err := viper.ReadInConfig()
	if err != nil {
		return err
	}
	viper.WatchConfig()
	viper.OnConfigChange(func(in fsnotify.Event) {
		Unmarshal()
	})
	return Unmarshal()
}

func Unmarshal() error {
	err := viper.Unmarshal(&gConfig)
	if err != nil {
		return err
	}
	// 获取非对称私钥
	global.ASymmetricPrivateKey, err = ioutil.ReadFile(gConfig.Crypto.AsymmetricPrivateKey)
	if err != nil {
		return err
	}
	cryptoInstance, ok := global.Crypto.Symmetric[crypto.CryptoSM4]
	if !ok {
		return errors.New("invalid crypto")
	}
	// 解密数据库配置
	source, err := cryptoInstance.DecryptWithBase64(gConfig.Database.Source, symmetricKey)
	if err != nil {
		return err
	}
	gConfig.Database.Source = string(source)
	// 解密Redis配置
	password, err := cryptoInstance.DecryptWithBase64(gConfig.Redis.Password, symmetricKey)
	if err != nil {
		return err
	}
	gConfig.Redis.Password = string(password)
	return nil
}

// Server 获取配置
func Server() ServerConfig {
	return gConfig.Server
}

// Database 获取配置
func Database() DatabaseConfig {
	return gConfig.Database
}

// Log 获取配置
func Log() LogConfig {
	return gConfig.Log
}

// Redis 获取配置
func Redis() RedisConfig {
	return gConfig.Redis
}

func EMailSetting() EMailConfig {
	return gConfig.Email
}

func SmsSetting() SmsConfig {
	return gConfig.Sms
}

// MsgcodeGenerator 获取配置
func MsgcodeGenerator() MsgcodeGeneratorConfig {
	return gConfig.MsgcodeGenerato
}

// SnowFlake 获取配置
func SnowFlake() SnowFlakeConfig {
	return gConfig.SnowFlake
}

// UriControl 获取配置
func UriControl() UriControlConfig {
	return gConfig.UriControl
}

// Crypto 获取配置
func Crypto() CryptoConfig {
	return gConfig.Crypto
}

// Token 获取配置
func Token() TokenConfig {
	return gConfig.Token
}
